package com.user.infrastructure.listener;

import com.common.InterceptorChain.BusinessInterceptorChain;
import com.common.InterceptorChain.BusinessInterceptorChainFactory;
import com.event.DomainEvent;
import com.event.DomainEventListener;
import com.security.service.AuthenticateService;
import com.user.domain.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static com.user.domain.event.UserEventEnum.USER_DOMAIN;
import static com.user.domain.event.UserEventEnum.USER_INSERT_EVENT;

/**
 * 监听用户的增删改事件,随机通知认证中心进行更新操作
 * @author 大忽悠
 * @create 2022/10/11 21:53
 */
@Component
@Slf4j
public class SecurityUserListener extends DomainEventListener {
    private static final ExecutorService executor= Executors.newCachedThreadPool();
    private static final BusinessInterceptorChain businessInterceptorChain= BusinessInterceptorChainFactory.newBusinessInterceptorChain();
    private static final String businessContextKey="domainEvent";
    /**
     * 新增用户默认给予的角色
     */
    private static final String DEFAULT_NEW_USER_ROLE="commonUser";
    private final AuthenticateService authenticateService;

    public SecurityUserListener(AuthenticateService authenticateService) {
        this.authenticateService = authenticateService;
        initInterceptorChain();
    }

    private void initInterceptorChain() {
        //用户注册同步到注册中心
        businessInterceptorChain.addInterceptor(businessContext -> {
            DomainEvent domainEvent = (DomainEvent) businessContext.getAttr(businessContextKey);
            if(domainEvent.getEventType().equals(USER_INSERT_EVENT.getEventType())){
                User user = (User) domainEvent.getSource();
                //异步执行,避免抛出异常,导致业务线程逻辑回滚
                CompletableFuture.runAsync(()->{
                            authenticateService.addUser(user.getUsername(),user.getPassword(),DEFAULT_NEW_USER_ROLE);
                        },executor);
            }
            return true;
        });
    }


    /**
     * 是否支持当前领域事件
     *
     * @param domainEvent
     */
    @Override
    protected boolean supportDomainEvent(DomainEvent domainEvent) {
        return domainEvent.getDomain().equals(USER_DOMAIN);
    }

    /**
     * 处理接收到的领域事件
     *
     * @param domainEvent
     */
    @Override
    protected void doHandleDomainEvent(DomainEvent domainEvent) {
        HashMap<Object, Object> map = new HashMap<>();
        map.put(businessContextKey,domainEvent);
        businessInterceptorChain.interceptor(BusinessInterceptorChainFactory.newBusinessContext(map));
    }
}
